using System;
using System.Collections.Generic;
using UnityEngine;
#if UNITY_EDITOR
using UnityEditor;
#endif


namespace Mars.GpuInstance
{
    [ExecuteInEditMode]
    public class InstancerPrefab : MonoBehaviour
    {
        [Header("产生阴影的方式：DISABLE->不产生阴影 FOLLOW_LOD->跟随lod  AUTO_SELECT->选择最后一个非impostor层级")]
        public ShadowLod shadowLod = ShadowLod.AUTO_SELECT;
        [Header("计算包围盒时的倍数，把包围盒扩大一点，避免看到在边缘的时候模型被裁剪掉")]
        public float boxExtents = 2.0f;
        [Header("释放强制渲染，勾上就会忽略lod的起始层级限制")]
        public bool forceRender = false;
        public List<LodData> LodDatas = new List<LodData>();
        
        public Bounds GetMeshBounds()
        {
            var bounds = new Bounds();
            foreach (var lodData in LodDatas)
            {
                if (lodData == null)
                {
                    continue;
                }
                foreach (var render in lodData.renderDatas)
                {
                    if (render != null && render.meshRenderer)
                    {
                        bounds.Encapsulate(render.meshRenderer.bounds);
                    }
                }
            }
            return bounds;
        }
        
#if UNITY_EDITOR
        public void Refresh()
        {
            OnValidate();
            EditorUtility.SetDirty(gameObject);
        }
        
#endif
        private void OnValidate()
        {
#if UNITY_EDITOR
            if (Application.isBatchMode || Application.isPlaying)
            {
                return;
            }
            
            for (int i = 0; i < LodDatas.Count; i++)
            {
                var lodData = LodDatas[i];
                if (lodData != null)
                {
                    foreach (var renderData in lodData.renderDatas)
                    {
                        if (renderData.meshRenderer)
                        {
                            if (renderData.meshRenderer.sharedMaterial)
                            {
                                renderData.meshRenderer.sharedMaterial.enableInstancing = true;
                            }
                            var transformOffset = InstancerEditorUtil.GetTransformOffset(transform, renderData.meshRenderer.transform);
                            renderData.transformOffset = transformOffset;
                            renderData.Refresh();
                        }
                    }
                }
            }
            
            EditorUtility.SetDirty(gameObject);
#endif
        }
    }

    [Serializable]
    public class LodData : IComparable<LodData>
    {
        public int lodDis;
        public List<RenderData> renderDatas;

        public int CompareTo(LodData obj)
        {
            if (lodDis == obj.lodDis)
            {
                return 0;
            }
            else if (lodDis > obj.lodDis)
            {
                return 1;
            }

            return -1;
        }
    }

    [Serializable]
    public class RenderData
    {
        public MeshRenderer meshRenderer;
        [HideInInspector] public Mesh mesh;
        public List<Material> mats;
        [HideInInspector] public Matrix4x4 transformOffset;

        public RenderData(MeshRenderer _meshRenderer, Matrix4x4 _transformOffset)
        {
            transformOffset = _transformOffset;
            meshRenderer = _meshRenderer;
        }

        public void Refresh()
        {
            if (meshRenderer == null)
            {
                return;
            }
            mesh = meshRenderer.GetComponent<MeshFilter>().sharedMesh;
            mats = new List<Material>(meshRenderer.sharedMaterials);
        }
    }
}
